﻿using Newtonsoft.Json;
using Nop.Core.Domain.Catalog;
using Nop.Plugin.Misc.Reservations.Models;
using Nop.Plugin.Misc.Reservations.Services;
using Nop.Services.Catalog;
using Nop.Services.Configuration;
using Nop.Web.Framework.Controllers;
using Nop.Web.Framework.Security;
using System;
using System.Collections.Generic;
using System.Web.Mvc;
using System.Web.Script.Serialization;
using Telerik.Web.Mvc;

namespace Nop.Plugin.Misc.Reservations.Controllers 
{
    public class ReservationController : Controller
    {
        #region Fields

        private readonly ISettingService _settingService;
        private readonly IReservationService _reservationService;
        private readonly IProductService _productService;
        private readonly ReservationSettings _reservationSettings;

        #endregion

        #region Ctor

        public ReservationController(ISettingService settingService, 
            IReservationService reservationService, IProductService productService,
            ReservationSettings reservationSettings)
        {
            _settingService = settingService;
            _reservationService = reservationService;
            _productService = productService;
            _reservationSettings = reservationSettings;
        }

        #endregion

        #region Action Methods

        [HttpGet]
        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure()
        {
            var model = new ConfigurationModel
            {
                MaxAdvanceReserveDays = _reservationSettings.MaxAdvanceReserveDays,
                TimeDuration = _reservationSettings.TimeDuration,
            };
            return View("Nop.Plugin.Misc.Reservations.Views.Reservation.Configure", model);
        }

        [HttpPost]
        [AdminAuthorize]
        [ChildActionOnly]
        public ActionResult Configure(ConfigurationModel model)
        {
            if (!ModelState.IsValid)
            {
                return Configure();
            }
            _reservationSettings.MaxAdvanceReserveDays = model.MaxAdvanceReserveDays;
            _reservationSettings.TimeDuration = model.TimeDuration;
            _settingService.SaveSetting(_reservationSettings);

            return View("Nop.Plugin.Misc.Reservations.Views.Reservation.Configure", model);
        }

        [HttpGet]
        [NopHttpsRequirement(SslRequirement.No)]
        public ActionResult Index()
        {
            return View("Index");
        }

        [HttpGet]
        [Authorize]
        public ActionResult ReservationDaily(DateTime selectedDate, int productId, int quantity)
        {
            var model = _reservationService.ReservationDaily(selectedDate, productId, quantity);

            return View("Nop.Plugin.Misc.Reservations.Views.Reservation.ReservationDaily", model);
        }

        [HttpPost]
        public JsonResult SelectedSlot(DateTime selectedDate, int productId, int tableIndex, bool isCancelled)
        {
            var model = _reservationService.SelectedSlot(selectedDate, productId, tableIndex, isCancelled);
            var status = model.StatusMessage.ContainsKey((int)StatusMessageType.Error)
                || model.StatusMessage.ContainsKey((int)StatusMessageType.Warning);

            return Json(new
            {
                Status = JsonConvert.SerializeObject(!status),
                Messages = JsonConvert.SerializeObject(model.StatusMessage),
                BookedReservations = JsonConvert.SerializeObject(model.BookedReservations),
            });
        }

        // TODO: Convert parameter string[] to IDictionary<int, int>
        [HttpPost]
        public JsonResult AddToCart(string additionalItems)
        {
            var ser = new JavaScriptSerializer();
            Dictionary<string, string> dict = ser.Deserialize<Dictionary<string, string>>(additionalItems);
            var model = _reservationService.AddToCart(_reservationService.StringToIntDictionary(dict));
            var result = model.StatusMessage.ContainsKey((int)StatusMessageType.Error)
                || model.StatusMessage.ContainsKey((int)StatusMessageType.Warning);

            return Json(new
            {
                Status = JsonConvert.SerializeObject(!result),
                Message = JsonConvert.SerializeObject(model.StatusMessage),
            });
        }

        [HttpPost]
        public JsonResult BookedReservations(DateTime selectedDate)
        {
            var model = _reservationService.UpdatedBookedReservations(selectedDate);

            return Json(new
            {
                BookedReservations = JsonConvert.SerializeObject(model.BookedReservations),
            });
        }

        [HttpGet]
        public ActionResult Change(string emailAddress, DateTime reserveDate)
        {
            return View("Nop.Plugin.Misc.Reservations.Views.Reservation.ReservationDaily");
        }

        [HttpPost]
        public ActionResult Change(ReservationViewModel reservation)
        {
            return View("Nop.Plugin.Misc.Reservations.Views.Reservation.ReservationDaily");
        }

        [HttpPost, GridAction(EnableCustomBinding = true)]
        public ActionResult ProductList(GridCommand command)
        {
            var products = _productService.GetAllProducts();
            var model = new GridModel<Product>
            {
                Data = products,
                Total = products.Count,
            };
            return new JsonResult
            {
                Data = model,
            };
        }

        [GridAction(EnableCustomBinding = true)]
        public ActionResult RemoveFeaturedProduct(int id, GridCommand command)
        {
            return ProductList(command);
        }

        #endregion
    }
}
